package com.ds.common.util;


import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.lang.NonNull;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class BeanUtil {

    public static <T> void copyProperties(@NonNull Object source, @NonNull T target, boolean ignoreNull) throws BeansException {
        BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
    }

    public static <T> void copyProperties(@NonNull Object source, @NonNull T target) throws BeansException {
        BeanUtils.copyProperties(source, target);
    }

    public static <T> List<T> mapList(List<?> list, Class<T> targetClass) {
        return list.stream().map(item -> copyProperties(item, targetClass)).collect(Collectors.toList());
    }

    public static <T> T copyProperties(@NonNull Object source, @NonNull Class<T> targetClass) {
        try {
            T result = targetClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source, result);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper wrapper = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = wrapper.getPropertyDescriptors();
        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = wrapper.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
}
